#ifdef CONFIG_SENSOR_TESTER

#include "SensorTester.h"
#include "SdrTester.h"
#include "Sensor_Threshold.h"
#include "Debug.h"
#include "Sensor_HotSwap.h"

#define SENSORTESTER_MAX_SENSOR 10
static Sensor g_SensorTester[SENSORTESTER_MAX_SENSOR];
static Crb		g_SensorTester_ReqIpmbCrb;
static uint8 g_SensorTesterValue = 0;

uint8 SensorTester_Scan(Sensor* pSensor)
{
	return g_SensorTesterValue;
}

void SensorTester_Reset()
{
	Trace("%s()\n", _FUNC_);
	memset(g_SensorTester, 0, sizeof(g_SensorTester));
	g_SensorTesterValue = 0;
}

Bool SensorTester_CreateSensor(Sdr* pSdr)
{
	int i = 0;
	int k = 0;
	Sensor* pSensor = Null;
	uint8 sensorType = 0;
	uint8 shareCount = 0;
	uint8 eventType = 0;
	SensorFun scan = Null;
	GetEventDataFun GetEventData = Null;
	uint8 defaultValue = 0;
	
	for(i = 0; i < pSdr->m_RecordCount; i++)
	{
		if(Null ==  pSdr->m_pRecordArray[i]) continue;

		shareCount = 0;
		if(SDR_COMPACT_SENSOR == pSdr->m_pRecordArray[i]->m_Type)
		{
			sensorType = ((CompactSensorRecord*)pSdr->m_pRecordArray[i])->m_SensorType;
			eventType = ((CompactSensorRecord*)pSdr->m_pRecordArray[i])->m_EventType;
			shareCount = ((CompactSensorRecord*)pSdr->m_pRecordArray[i])->m_ShareCount;
			defaultValue = HANDLE_OPENED;
		}
		else if(SDR_FULL_SENSOR == pSdr->m_pRecordArray[i]->m_Type)
		{
			sensorType = ((FullSensorRecord*)pSdr->m_pRecordArray[i])->m_SensorType;
			eventType = ((FullSensorRecord*)pSdr->m_pRecordArray[i])->m_EventType;
			defaultValue = 0;
		}
		else
		{
			continue;
		}

		scan = (SensorFun)SensorTester_Scan;
		GetEventData = Null;
		
		switch(eventType)
		{
			case ET_THRESHOLD:
				GetEventData = (GetEventDataFun)Sensor_ThresholdGetEventData;
				break;
			default:
				GetEventData = (GetEventDataFun)Sensor_GetEventData;
				break;
		}

		if(scan && GetEventData)
		{
			for(k = 0; k <= shareCount; k++)
			{
				pSensor = Sensor_New(g_SensorTester, SENSORTESTER_MAX_SENSOR);
				if(pSensor)
				{
					Sensor_Init(pSensor
						, pSdr->m_pRecordArray[i]
						, k
						, scan
						, GetEventData
						, &g_SensorTester_ReqIpmbCrb
						, Null
						, defaultValue
						);
				}
				else
				{
					Assert(pSensor);
				}
			}	
		}
		else
		{
			Assert(False);
		}
	}

	return True;
}

Sensor* Sensortester_Get(uint8 sensorId)
{
	int i  = 0;

	for(i = 0; i < SENSORTESTER_MAX_SENSOR; i++)
	{
		if(g_SensorTester[i].m_pRecodHeader == Null) return Null;

		if(g_SensorTester[i].m_SensorId == sensorId)
		{
			return &g_SensorTester[i];
		}
	}

	return Null;
}

static Sensor* SensorTester_GetSensor(uint8 sensorId)
{
	int i = 0;
	uint8 rawValue = 0;
	uint8 cmValue = 0;
	Sensor* pSensor = Null;
	FullSensorRecord* pFullSensorRecord = Null;
	Sdr* pSdr = SdrTester_Create();
	Bool bRet = True;

	SensorTester_CreateSensor(pSdr);

	pSensor = Sensortester_Get(sensorId);	//4
	pFullSensorRecord = (FullSensorRecord*)pSensor->m_pRecodHeader;

	Trace("Sensor[%s][%d],ThreadHold: [%02d]-[%02d]-[%02d]-[%02d]-[%02d]-[%02d]:[+%02d]-[-%02d]\n"
		, pFullSensorRecord->m_IdString
		, pSensor->m_SensorId
		, pFullSensorRecord->m_UpperNonRecoverable
		, pFullSensorRecord->m_UpperCiritcal
		, pFullSensorRecord->m_UpperNonCiritcal
		, pFullSensorRecord->m_LowerNonCiritcal
		, pFullSensorRecord->m_LowerCiritcal
		, pFullSensorRecord->m_LowerNonRecoverable
		, pFullSensorRecord->m_PoHysteresis
		, pFullSensorRecord->m_NeHysteresis
		);
	return pSensor;
}


Bool SensorTester_ThresholdInputTest(Sensor* pSensor, uint8 cmRawValue, uint8 rawValue, uint8 offset)
{
	Bool isDeassert = False;
	FullSensorRecord* pFullSensorRecord = (FullSensorRecord*)pSensor->m_pRecodHeader;
	if(rawValue > cmRawValue)
	{
		//Go Up
		if(rawValue >= pFullSensorRecord->m_UpperNonCiritcal)
		{
			isDeassert = 0;
		}
		else
		{
			isDeassert = 1;
		}
	}
	else if(rawValue < cmRawValue) //Go Low
	{
		if(rawValue <= pFullSensorRecord->m_LowerNonCiritcal)
		{
			isDeassert = 0;
		}
		else
		{
			isDeassert = 1;
		}
	}
	else
	{
		return True;
	}
	pSensor->m_ReceiverValue = cmRawValue;
	pSensor->m_RawValue = rawValue;
	Trace("State Changed: [%02d]->[%02d]\n", pSensor->m_ReceiverValue, pSensor->m_RawValue);

	pSensor->GetEventData(pSensor);

	if(pSensor->m_EventData.m_EventDir != pSensor->m_ReceiverEventData.m_EventDir
		|| pSensor->m_EventData.m_EventData1.m_Offset != pSensor->m_ReceiverEventData.m_EventData1.m_Offset)
	{
		Trace("Event Data: [%s][%s], Threshold=[%d], readingValue=[%s]\n"
			, pSensor->m_EventData.m_EventDir == 0 ? "A" : "D"
			, g_pThreadholdString[pSensor->m_EventData.m_EventData1.m_Offset]
			, pSensor->m_EventData.m_EventData3
			, SensorEventType_GetString(pSensor->m_ReadingEvent)
			);
		memcpy(&pSensor->m_ReceiverEventData, &pSensor->m_EventData, sizeof(EventData));
		pSensor->m_ReceiverValue = pSensor->m_RawValue;
	}
	else
	{
		//Trace("No Event Data\n");
		return True;
	}

	if(pSensor->m_EventData.m_EventDir == isDeassert
		&& pSensor->m_EventData.m_EventData1.m_Offset == offset)
	{
		return True;
	}
	else

	{
		return False;
	}


	return True;
}

//		,{{2, L"AGH(UPPER_RECOVERABLE)",(TesterFun)CTestSensor::SensorCreatPlatformEvent},{TEMPERATURE1_SENSOR_ID, min,max, thres}, {AGH_UNR, thresHold, reading}}
Bool SensorTester_ThresHolde(uint32 input[], uint32 output[])
{
	uint32 j = 0;
	uint32 i = 0;
	Bool bRet = True;
	Sensor* pSensor = Null;
	FullSensorRecord* pFullSensorRecord = Null;
	Bool isGreateEvent = output[0];
	EventData eventData;
		
	Sdr* pSdr = SdrTester_Create();

    eventData.m_EventDir  	= output[1];
    eventData.m_EventType 	= output[2];
    eventData.m_EventData1.m_Data2Format = 1;
    eventData.m_EventData1.m_Data3Format = 1;
    eventData.m_EventData1.m_Offset 		= output[3];
    eventData.m_EventData2	= 0;
    eventData.m_EventData3	= output[4];
	
	SensorTester_CreateSensor(pSdr);
	pSensor = Sensortester_Get(input[0]);

	if(pSensor->m_pRecodHeader->m_Type != SDR_FULL_SENSOR)
	{
		bRet = False;
		goto End;
	}
	
	pFullSensorRecord = (FullSensorRecord*)pSensor->m_pRecodHeader;

	Trace("Sensor[%s][%d],ThreadHold: [%02d]-[%02d]-[%02d]-[%02d]-[%02d]-[%02d]:[+%02d]-[-%02d]\n"
		, pFullSensorRecord->m_IdString
		, pSensor->m_SensorId
		, pFullSensorRecord->m_UpperNonRecoverable
		, pFullSensorRecord->m_UpperCiritcal
		, pFullSensorRecord->m_UpperNonCiritcal
		, pFullSensorRecord->m_LowerNonCiritcal
		, pFullSensorRecord->m_LowerCiritcal
		, pFullSensorRecord->m_LowerNonRecoverable
		, pFullSensorRecord->m_PoHysteresis
		, pFullSensorRecord->m_NeHysteresis
		);


	Trace("State Changed: [%02d-%02d]->[%02d-%02d]\n", input[1], input[2], input[3], input[4]);
	for(i = input[1]; i <= input[2]; i++)
	{
		pSensor->m_ReceiverValue = i;
		
		for(j =  input[3]; j <= input[4]; j++)
		{
			pSensor->m_RawValue = j;
			
			pSensor->GetEventData(pSensor);

			eventData.m_EventData2 = pSensor->m_RawValue;
			if(isGreateEvent)
			{
				if(memcmp(&pSensor->m_EventData, &eventData, sizeof(EventData)) != 0)
				{
					bRet = False;
					goto End;
				}
				if(pSensor->m_ReadingEvent != output[5])
				{
					bRet = False;
					goto End;
				}

			}
			else
			{
				if(pSensor->m_EventData.m_EventData1.m_Data2Format != 0) 
				{
					bRet = False;
					goto End;
				}
			}
		}
	}

End:
	if(pSensor->m_EventData.m_EventData1.m_Data2Format)
	{
		Trace("Gerenate Event Data: [%s][%s], Threshold=[%d], readingValue=[%s]\n"
			, pSensor->m_EventData.m_EventDir == 0 ? "A" : "D"
			, g_pThreadholdString[pSensor->m_EventData.m_EventData1.m_Offset]
			, pSensor->m_EventData.m_EventData3
			, SensorEventType_GetString(pSensor->m_ReadingEvent)
			);
	}
	else
	{
		Trace("Gerenate Event Data: Nothing.\n");
	}

	if(!bRet)
	{
		Trace("State Changed: [%02d]->[%02d]\n", pSensor->m_ReceiverValue, pSensor->m_RawValue);
	}
	
	SensorTester_Reset();
	return bRet;
}

//UpperNonRecoverable 	--------------------------------
//UpperCiritcal 		--------------------------------
//UpperNonCiritcal 		--------------------------------
//LowerNonCiritcal 		--------------------------------
//LowerCiritcal 		--------------------------------
//LowerNonRecoverable 	--------------------------------

Bool SensorTester_ThresHoldGetEventData(uint8 SensorId)
{
	uint8 newValue = 0;
	uint8 olderValue = 0;
	Bool bRet = True;
	uint8 maxValue = 110;
	uint8 offset = INVALID_EVENT_STATES;
	Sensor* pSensor = Null;
	FullSensorRecord* pFullSensorRecord = Null;
	Threshold	thresholdItem;
	Threshold* pThreshold = &thresholdItem;
	
	Sdr* pSdr = SdrTester_Create();

	SensorTester_CreateSensor(pSdr);
	pSensor = Sensortester_Get(SensorId);

	pFullSensorRecord = (FullSensorRecord*)pSensor->m_pRecodHeader;

	thresholdItem.m_UpperNonRecoverable = pFullSensorRecord->m_UpperNonRecoverable;
	thresholdItem.m_UpperCiritcal = pFullSensorRecord->m_UpperCiritcal;
	thresholdItem.m_UpperNonCiritcal = pFullSensorRecord->m_UpperNonCiritcal;
	thresholdItem.m_LowerNonCiritcal = pFullSensorRecord->m_LowerNonCiritcal;
	thresholdItem.m_LowerCiritcal = pFullSensorRecord->m_LowerCiritcal;
	thresholdItem.m_LowerNonRecoverable = pFullSensorRecord->m_LowerNonRecoverable;
	thresholdItem.m_PoHysteresis = pFullSensorRecord->m_PoHysteresis;
	thresholdItem.m_NeHysteresis = pFullSensorRecord->m_NeHysteresis;

	maxValue = pFullSensorRecord->m_UpperNonRecoverable + 5;
	Trace("Sensor[%s][%d],ThreadHold: [%02d]-[%02d]-[%02d]-[%02d]-[%02d]-[%02d]:[+%02d]-[-%02d]\n"
		, pFullSensorRecord->m_IdString
		, pSensor->m_SensorId
		, pFullSensorRecord->m_UpperNonRecoverable
		, pFullSensorRecord->m_UpperCiritcal
		, pFullSensorRecord->m_UpperNonCiritcal
		, pFullSensorRecord->m_LowerNonCiritcal
		, pFullSensorRecord->m_LowerCiritcal
		, pFullSensorRecord->m_LowerNonRecoverable
		, pFullSensorRecord->m_PoHysteresis
		, pFullSensorRecord->m_NeHysteresis
		);

	for(newValue = 0; newValue < maxValue; newValue++)
	{
		for(olderValue = 0; olderValue < maxValue; olderValue++)
		{
			memset(&pSensor->m_EventData, 0, sizeof(pSensor->m_ReceiverEventData));
			memset(&pSensor->m_ReceiverEventData, 0, sizeof(pSensor->m_ReceiverEventData));
			if(olderValue == 0 && newValue == 70)
			{
				bRet = True;
			}
			if(newValue > olderValue)	//Go Up
			{
				if(newValue >= pThreshold->m_UpperNonRecoverable)
				{
					if(olderValue < pThreshold->m_UpperNonRecoverable)
					{
						offset = UPPER_NON_RECOVERABLE_H;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue >= pThreshold->m_UpperCiritcal)
				{
					if(olderValue < pThreshold->m_UpperCiritcal)
					{
						offset = UPPER_CRITICAL_H;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue >= pThreshold->m_UpperNonCiritcal)
				{
					if(olderValue < pThreshold->m_UpperNonCiritcal)
					{
						offset = UPPER_NO_CRITICAL_H;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue >= pThreshold->m_LowerNonCiritcal + pThreshold->m_PoHysteresis)
				{
					if(olderValue <= pThreshold->m_LowerNonCiritcal)
					{
						offset = LOWER_NO_CRITICAL_L;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue >= pThreshold->m_LowerCiritcal + pThreshold->m_PoHysteresis)
				{
					if(olderValue <= pThreshold->m_LowerCiritcal)
					{
						offset = LOWER_CRITICAL_L;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue >= pThreshold->m_LowerNonRecoverable + pThreshold->m_PoHysteresis)
				{
					if(olderValue <= pThreshold->m_LowerNonRecoverable)
					{
						offset = LOWER_NON_RECOVERABLE_L;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
			}
			else if(newValue < olderValue)	//Go Down
			{
				if(newValue > pThreshold->m_UpperNonRecoverable - pThreshold->m_NeHysteresis)
				{
					offset = INVALID_EVENT_STATES;
				}
				else if(newValue > pThreshold->m_UpperCiritcal - pThreshold->m_NeHysteresis)
				{
					if(olderValue >= pThreshold->m_UpperCiritcal)
					{
						offset = UPPER_NON_RECOVERABLE_H;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue > pThreshold->m_UpperNonCiritcal - pThreshold->m_NeHysteresis)
				{
					if(olderValue >= pThreshold->m_UpperNonCiritcal)
					{
						offset = UPPER_CRITICAL_H;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue > pThreshold->m_LowerNonCiritcal)
				{
					if(olderValue >= pThreshold->m_UpperNonCiritcal)
					{
						offset = UPPER_NO_CRITICAL_H;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue > pThreshold->m_LowerCiritcal)
				{
					if(olderValue >= pThreshold->m_LowerNonCiritcal)
					{
						offset = LOWER_NO_CRITICAL_L;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else if(newValue > pThreshold->m_LowerNonRecoverable)
				{
					if(olderValue >= pThreshold->m_LowerCiritcal)
					{
						offset = LOWER_CRITICAL_L;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
				else
				{
					if(olderValue >= pThreshold->m_LowerNonRecoverable)
					{
						offset = LOWER_NON_RECOVERABLE_L;
					}
					else
					{
						offset = INVALID_EVENT_STATES;
					}
				}
			}
			
			
			if(!SensorTester_ThresholdInputTest(pSensor, olderValue, newValue, offset))
			{
				//Assert(False);
				bRet = False;
				goto End;
			}
		}
	}

	SensorTester_Reset();
End:
	return bRet;
}

Bool SensorTester_DiscreteInputTest(Sensor* pSensor, uint8 cmRawValue, uint8 rawValue)
{
	Bool isDeassert = False;
	pSensor->m_ReceiverValue = cmRawValue;
	pSensor->m_RawValue = rawValue;
	Trace("State Changed: [%02d]->[%02d]\n", pSensor->m_ReceiverValue, pSensor->m_RawValue);

	pSensor->GetEventData(pSensor);

	if(pSensor->m_EventData.m_EventDir != pSensor->m_ReceiverEventData.m_EventDir
		|| pSensor->m_EventData.m_EventData1.m_Offset != pSensor->m_ReceiverEventData.m_EventData1.m_Offset)
	{
		EventData_Dump(&pSensor->m_EventData);
		memcpy(&pSensor->m_ReceiverEventData, &pSensor->m_EventData, sizeof(EventData));
		pSensor->m_ReceiverValue = pSensor->m_RawValue;
	}
	else
	{
		Trace("No Event Data\n");
		return True;
	}

	if(pSensor->m_EventData.m_EventDir == isDeassert
		&& pSensor->m_EventData.m_EventData1.m_Offset == rawValue)
	{
		return True;
	}
	else

	{
		return False;
	}
}
Bool SensorTester_DiscreteGetEventData(uint32 input[], uint32 output[])
{
	int i = 0;
	Sensor* pSensor = Null;
	CompactSensorRecord* pCompactSensorRecord = Null;
	Sdr* pSdr = SdrTester_Create();
	Bool bRet = True;

	SensorTester_CreateSensor(pSdr);

	pSensor = Sensortester_Get(input[0]);
	pCompactSensorRecord = (CompactSensorRecord*)pSensor->m_pRecodHeader;

	Trace("Sensor[%s][%d],AssertMask = [0x%04x], DeassertMask = [0x%04x]\n"
		, pCompactSensorRecord->m_IdString
		, pSensor->m_SensorId
		, pCompactSensorRecord->m_LowerThresholdMask
		, pCompactSensorRecord->m_UpperThresholdMask
		);

	pSensor->m_ReceiverValue = input[1];
	pSensor->m_RawValue = input[2];
	Trace("State Changed: [%02d]->[%02d]\n", pSensor->m_ReceiverValue, pSensor->m_RawValue);

	pSensor->GetEventData(pSensor);

	if(pSensor->m_EventData.m_EventDir != output[0])
	{
		bRet = False;
		goto End;
	}
	if(pSensor->m_EventData.m_EventData1.m_Offset != output[1])
	{
		bRet = False;
		goto End;
	}

End:
	SensorTester_Reset();
	return bRet;
}
//////////////////////////////////////////////////////////
#endif
